/*
NoBuffer Notepad Copyright (C) 2015  Mahmoud Jaoune

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "videobuffer.h"
#include "textedit.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    fileReadProgressGUI = new NBN_ProgressWidget(0, "Loading file", "Loading...");
    fileReadProgressGUI->hide();

    ui->selectBlock->setValidator(new QIntValidator(0, 90000000, this));

    connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(on_AboutAction()));
    connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(on_NewAction()));
    connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(on_OpenAction()));
    connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(on_SaveAction()));
    connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(on_SaveAsAction()));
    connect(ui->actionCut_2, SIGNAL(triggered()), this, SLOT(on_CutAction()));
    connect(ui->actionCopy_2, SIGNAL(triggered()), this, SLOT(on_CopyAction()));
    connect(ui->actionPaste, SIGNAL(triggered()), this, SLOT(on_PasteAction()));
    connect(ui->actionUndo, SIGNAL(triggered()), this, SLOT(on_UndoAction()));
    connect(ui->actionRedo, SIGNAL(triggered()), this, SLOT(on_RedoAction()));
    connect(ui->actionSettings, SIGNAL(triggered()), this, SLOT(on_SettingsAction()));
    connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(on_ExitAction()));

    //If settings.ini does not exist, create one with default values
    if(!QFile("settings.ini").exists())
    {
        QSettings settingsFile("settings.ini", QSettings::IniFormat);
        settingsFile.beginGroup("options");
        settingsFile.setValue("blockSize", "200000");
        settingsFile.setValue("font", "MS Shell Dlg 2,8.25,-1,5,50,0,0,0,0,0");
        settingsFile.endGroup();
    }

}

MainWindow::~MainWindow()
{
    delete ui;
}

/*
 * This function adds a new tab with a TextEdit inside it and then loads the file in that TextEdit
 */
void MainWindow::loadFile(const char *fileName)
{
    NBN_TextEdit *textEdit = new NBN_TextEdit(ui->mainWidget);
    textEdit->setObjectName(QString(fileName));
    textEdit->NBN_LoadFile(fileName);

    QString tabName;
    tabName.push_back(QString(fileName));

    ui->mainWidget->addTab(textEdit, tabName);
}

/*
 * In-case MainWindow gets resized, then resize its contents
 */
void MainWindow::resizeEvent(QResizeEvent *event)
{
    QApplication::processEvents();
    ui->toolBar->resize(event->size().width(), ui->toolBar->height());
    ui->mainWidget->resize(event->size().width(), event->size().height() - 65);
    ui->toolBar->move(ui->toolBar->x(), event->size().height() - ui->statusBar->height() - ui->toolBar->height() - ui->menuBar->height());
    emit WindowResized(event->size().width(), event->size().height());
}

/*
 * This shows the process of loading a file (In bytes-loaded percentage)
 */
void MainWindow::NBN_setProgress(unsigned int progress, unsigned int total)
{
    fileReadProgressGUI->setProgress(progress, total);
    fileReadProgressGUI->show();
}

/*
 * Hides the loading file process GUI when file loading is done
 */
void MainWindow::NBN_endProgressGUI()
{
    fileReadProgressGUI->setProgress(0, 0);
    fileReadProgressGUI->hide();
}

/*
 * When file loading gets finished, this will set the total amount of blocks a file can be divided into to the targetted
 * tab.
 */
void MainWindow::NBN_SetTotalBlocks(int nBlocks, QString currentTab)
{
    if(ui->mainWidget->tabText(ui->mainWidget->currentIndex()) == currentTab)
    {
        ui->nBlocksLabel->setText(QString::number(nBlocks));
        ui->selectBlock->setText("1");
    }

    BlockDB bd;
    bd.currentBlock = 1;
    bd.totalBlocks = nBlocks;

    blockDB.insert(currentTab, bd);

    ui->statusBar->showMessage("File loaded", 3000);
}

/*
 * When "Go" button is clicked, load specified block from file.
 */
void MainWindow::on_goBlock_clicked()
{
    int blockNo = ui->selectBlock->text().toInt();
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    if(blockNo > 0 && blockNo <= ui->nBlocksLabel->text().toInt() && ui->nBlocksLabel->text().toInt() > 1)
    {
        BlockDB bd;
        bd.currentBlock = blockNo;
        bd.totalBlocks = ui->nBlocksLabel->text().toInt();

        NBN_TextEdit *currentTextEdit = this->findChild<NBN_TextEdit *>(currentTab);

        blockDB.insert(currentTab, bd);
        emit NBN_OnSelectBlock(blockNo, currentTextEdit);
    }
}

void MainWindow::on_mainWidget_currentChanged(int index)
{
    QString currentTab = ui->mainWidget->tabText(index);
    BlockDB currentDB;
    currentDB = blockDB.value(currentTab);

    ui->selectBlock->setText(QString::number(currentDB.currentBlock));
    ui->nBlocksLabel->setText(QString::number(currentDB.totalBlocks));
}

/*
 * If a tab gets closed, then clean up everything behind that file.
 */
void MainWindow::on_mainWidget_tabCloseRequested(int index)
{
    blockDB.remove(ui->mainWidget->tabText(index));

    emit NBN_CleanThread(ui->mainWidget->tabText(index));

    ui->mainWidget->removeTab(index);
}

/* MenuBar Actions */
void MainWindow::on_NewAction()
{
    QString fileToSave = QFileDialog::getSaveFileName(this, "New text file...", QString(), "Text Files (*.*)");

    if(!fileToSave.isEmpty())
    {
        QFile newFile(fileToSave);
        newFile.open(QFile::WriteOnly | QFile::Truncate);
        newFile.close();

        loadFile(fileToSave.toStdString().c_str());
    }
}

void MainWindow::on_OpenAction()
{
    QString fileToOpen = QFileDialog::getOpenFileName(this, "Open text file...", QString(), "Text Files (*.*)");

    if(!fileToOpen.isEmpty())
    {
        loadFile(fileToOpen.toStdString().c_str());
    }
}

void MainWindow::on_SaveAction()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    emit NBN_SendSave(currentTab, blockDB.value(currentTab));
}

void MainWindow::on_SaveAsAction()
{
    QString fileToSave = QFileDialog::getSaveFileName(this, "Save text file...", QString(), "Text Files (*.*)");

    if(!fileToSave.isEmpty())
    {
        QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

        emit NBN_SendSaveAs(currentTab, fileToSave, blockDB.value(currentTab));
    }

}

void MainWindow::on_ExitAction()
{
    this->close();
}

void MainWindow::on_UndoAction()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    emit NBN_SendUndo(currentTab);
}

void MainWindow::on_RedoAction()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    emit NBN_SendRedo(currentTab);
}

void MainWindow::on_CutAction()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    emit NBN_SendCut(currentTab);
}

void MainWindow::on_CopyAction()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    emit NBN_SendCopy(currentTab);
}

void MainWindow::on_PasteAction()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());

    emit NBN_SendPaste(currentTab);
}

void MainWindow::on_SettingsAction()
{
    settingsdialog *settings = new settingsdialog(this); //There is a memory leak here (I know)
    settings->show();
    connect(settings, SIGNAL(reloadSettings()), this, SLOT(sendReloadSettings()));
}

void MainWindow::sendReloadSettings()
{
    emit reloadSettings();
}

void MainWindow::on_AboutAction()
{
    aboutdialog *About = new aboutdialog(this); //There is a memory leak here (I know)
    About->show();
    connect(About, SIGNAL(destroyed()), About, SLOT(deleteLater()));
}

/* End of MenuBar actions */

void MainWindow::on_backBlock_clicked()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());
    int blockNo = blockDB.value(currentTab).currentBlock - 1;

    if(blockNo > 0 && blockNo <= ui->nBlocksLabel->text().toInt() && ui->nBlocksLabel->text().toInt() > 1)
    {
        BlockDB bd;
        bd.currentBlock = blockNo;
        bd.totalBlocks = ui->nBlocksLabel->text().toInt();

        NBN_TextEdit *currentTextEdit = this->findChild<NBN_TextEdit *>(currentTab);

        blockDB.insert(currentTab, bd);

        ui->selectBlock->setText(QString::number(blockNo));

        emit NBN_OnSelectBlock(blockNo, currentTextEdit);
    }
}

void MainWindow::on_nextBlock_clicked()
{
    QString currentTab = ui->mainWidget->tabText(ui->mainWidget->currentIndex());
    int blockNo = blockDB.value(currentTab).currentBlock + 1;

    if(blockNo > 0 && blockNo <= ui->nBlocksLabel->text().toInt() && ui->nBlocksLabel->text().toInt() > 1)
    {
        BlockDB bd;
        bd.currentBlock = blockNo;
        bd.totalBlocks = ui->nBlocksLabel->text().toInt();

        NBN_TextEdit *currentTextEdit = this->findChild<NBN_TextEdit *>(currentTab);

        blockDB.insert(currentTab, bd);

        ui->selectBlock->setText(QString::number(blockNo));

        emit NBN_OnSelectBlock(blockNo, currentTextEdit);
    }
}
